﻿/**********************************************************
 ●项目：Smartkernel
 ●公司：智能核心信息技术研发中心
 ●作者：曹艳白
 ●邮箱：caoyanbai@gmail.com
 ●创建：2008-08-10
 ●版本：1.0
**********************************************************/
using System;
using Smartkernel.Exceptions;
using Smartkernel.Resource;

namespace Smartkernel.Caching
{
    /// <summary>
    /// 缓存器的缓存项
    /// </summary>
    /// <typeparam name="TValue">缓存项的类型</typeparam>
    public partial class SmartCacherValue<TValue>
    {
        #region 属性、字段和构造函数
        private bool refreshCreateTime;
        /// <summary>
        /// 是否更新创建时间，如果为true则更新，每次对象被访问都会刷新创建时间为当前时间，会影响到超时清理条件
        /// </summary>
        public bool RefreshCreateTime
        {
            get
            {
                return this.refreshCreateTime;
            }
        }
        private int cacheTime;
        /// <summary>
        /// 对象的缓存时间，小于等于0表示永久，其他值表示缓存的秒数
        /// </summary>
        public int CacheTime
        {
            get
            {
                return this.cacheTime;
            }
        }
        private int minCounter;
        /// <summary>
        /// 在指定缓存时间内，调用次数小于这个值的将被清理，小于等于0代表此条件不起作用
        /// </summary>
        public int MinCounter
        {
            get
            {
                return this.minCounter;
            }
        }
        private TValue value;
        /// <summary>
        /// 保存的实际缓存项
        /// </summary>
        public TValue Value
        {
            get
            {
                //缓存项被访问时，根据条件刷新计数器
                this.Refresh();
                return this.value;
            }
        }
        private DateTime createTime;
        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreateTime
        {
            get
            {
                return this.createTime;
            }
        }
        private long counter;
        /// <summary>
        /// 调用次数计数器
        /// </summary>
        public long Counter
        {
            get
            {
                return this.counter;
            }
        }
        /// <summary>
        /// 缓存对象是否已超时
        /// </summary>
        public bool IsOverdue
        {
            get
            {
                DateTime now = DateTime.Now;
                if (MinCounter > 0 && Counter < MinCounter && CacheTime > 0)
                {
                    //要求最低调用次数大于0，且调用次数小于最低调用次数，且缓存时间不是永久
                    return true;
                }
                else if (MinCounter <= 0 && CacheTime > 0 && CreateTime.AddSeconds(CacheTime) < now)
                {
                    //不受调用次数影响时，创建时间已经超时
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="value">保存的实际缓存项</param>
        /// <param name="cacheTime">对象的缓存时间，小于等于0表示永久，其他值表示缓存的秒数</param>
        /// <param name="refreshCreateTime">是否更新创建时间，如果为true则更新，每次对象被访问都会刷新创建时间为当前时间，会影响到超时清理条件</param>
        /// <param name="minCounter">在指定缓存时间内，调用次数小于这个值的将被清理，小于等于0代表此条件不起作用</param>
        public SmartCacherValue(TValue value, int cacheTime, bool refreshCreateTime, int minCounter)
        {
            if (value == null)
            {
                throw new SmartException(SmartExceptionMessageResource.SmartCacherValue_value_Null);
            }

            this.counter = 0;
            this.value = value;
            this.createTime = DateTime.Now;
            this.cacheTime = cacheTime;
            this.minCounter = minCounter;
            this.refreshCreateTime = refreshCreateTime;
        }
        #endregion
    }
    public partial class SmartCacherValue<TValue>
    {
        #region 方法
        /// <summary>
        /// 刷新对象，每次对象被访问都会刷新创建时间和计数器
        /// </summary>
        public void Refresh()
        {
            if (this.refreshCreateTime)
            {
                this.createTime = DateTime.Now;
            }
            lock (this)
            {
                if (this.counter != long.MaxValue)
                {
                    this.counter++;
                }
            }
        }
        #endregion
    }
}
